#include "database.h"
ChatDatabase *ChatDatabase::instance = nullptr;
ChatDatabase::ChatDatabase(/* args */)
{
    userinfo = new User();
}

ChatDatabase::~ChatDatabase()
{
}
ChatDatabase *ChatDatabase::getChatDatabase()
{
    if (instance == nullptr)
    {
        instance = new ChatDatabase();
    }
    return instance;
}
// 随机生成11位账号
void ChatDatabase::make_uid(string &uid)
{

    srand(time(0));

    char tmp = 0;
    for (int i = 0; i < 11; ++i)
    {
        int mode = random() % 2;
        switch (mode)
        {
        case 0:
            tmp = random() % 10;
            tmp += '0';
            break;
        case 1:
            tmp = random() % 26;
            tmp += 'A';
            break;
        default:
            tmp = random() % 26;
            tmp += 'a';
            break;
        }
        uid += tmp;
    }
}
// 密码加密
//  string ChatDatabase::strEncrypt(const string &str)
// {
//     string output = str;
//     for (size_t i = 0; i < str.length(); ++i)
//     {
//         output[i] ^=Key;
//     }
//     return output;
// }
// 数据库连接
void ChatDatabase::my_database_connect()
{
    this->mysql = mysql_init(NULL);

    this->mysql = mysql_real_connect(this->mysql, URL, USER, PASSWORD,
                                     DBNAME, 0, NULL, 0);
    if (NULL == this->mysql)
    {
        cout << "mysql_real_connect error" << endl;
    }
    else
    {
        cout << "连接成功" << endl;
    }
}
//  读消息
int ChatDatabase::my_database_get_data(vector<string> &array, const char *sqlscript)
{

    MYSQL_RES *res = get_MYSQL_RES(this->mysql, sqlscript);
    if (NULL == res)
    {
        return -1;
    }

    int column = mysql_num_fields(res);
    int rn = mysql_num_rows(res);
    // cout << "column: " << column << endl;

    MYSQL_ROW row;
    while ((row = mysql_fetch_row(res)))
    {

        string tmp;
        if (column == 1)
        {
            tmp += row[0]; // 只有一列数据，push进vector里，vector的 索引 是 行
            array.push_back(tmp);
        }
        else
        {
            if (rn == 1)
            { // 只有一行数据，push进vector里，vector的 索引 是 列
                for (int i = 0; i < column; ++i)
                {
                    tmp += row[i];
                    array.push_back(tmp);
                    tmp.clear();
                }
            }
            else
            { // 多行多列，vector的 索引 是 行，每列用 '|' 隔开
                for (int i = 0; i < column; ++i)
                {
                    tmp += row[i];
                    tmp += '|';
                }
                array.push_back(tmp);
            }
        }
    }

    if (rn == 1 || column == 1)
        return 1;
    else if (rn == 0)
        return 0;
    else
        return 2;
}
// sql语句执行函数
MYSQL_RES *ChatDatabase::get_MYSQL_RES(MYSQL *mysql, const char *sqlscript)
{
    const char *csname = "utf8"; // 编码格式
    mysql_set_character_set(mysql, csname);
    if (mysql_query(mysql, sqlscript) != 0)
    {
        cout << "mysql_query error" << endl;
        return nullptr;
    }

    MYSQL_RES *res = mysql_store_result(mysql);
    // if (NULL == res)
    // {
    //     cout << "mysql_store_result error" << endl;
    //     return nullptr;
    // }
    // else
    // {
    return res;
    //}
}
// 根据账号返回id
int ChatDatabase::getid(const char *loginid)
{
    ostringstream buffer;
    buffer << "select U_ID from user where U_LoginID = '" << loginid << "';";
    string statement = buffer.str();
    MYSQL_RES *res = get_MYSQL_RES(this->mysql, statement.c_str());
    if (NULL == res)
    {
        cout << "sql语句执行错误" << endl;
        return -1;
    }
    MYSQL_ROW row = mysql_fetch_row(res);
    if (row == nullptr)
    {
        return -1;
    }
    int id = atoi(row[0]);
    return id;
}
// 根据id返回账号
char *ChatDatabase::getlogin(int id)
{
    ostringstream buffer;
    buffer << "select U_LoginID from user where U_ID = " << id << ";";
    string statement = buffer.str();
    MYSQL_RES *res = get_MYSQL_RES(this->mysql, statement.c_str());
    if (NULL == res)
    {
        cout << "sql语句执行错误" << endl;
        exit(1);
    }
    MYSQL_ROW row = mysql_fetch_row(res);
    if (row == nullptr)
    {
        exit(1);
    }
    char *loginid = row[0];
    return loginid;
}
// 用户注册
string ChatDatabase::my_database_user_register(const string &name, const string &password)
{

    // 随机生成不重复的用户uid
    string uid;
    make_uid(uid); // 随机产生11位数字

    ostringstream buffer;
    buffer << "select U_LoginID from user where U_LoginID = '" << uid << "';";
    string statement = buffer.str();

    MYSQL_RES *res = get_MYSQL_RES(this->mysql, statement.c_str());
    if (res == NULL)
        return "false";

    while (mysql_num_rows(res) != 0)
    {
        // 有重复就清除重新生成
        uid.clear();
        make_uid(uid);

        buffer.str("");
        buffer << "select uid from chatuser where uid = '" << uid << "';";
        string s = buffer.str();

        res = get_MYSQL_RES(this->mysql, s.c_str());
    }

    // 注册用户数据
    buffer.str("");
    statement.clear();
    // string mpassword = strEncrypt(password);
    buffer << "insert into user(U_LoginID,U_NickName,U_PassWord) "
           << "values ('" << uid << "','" << name << "','" << password << "');";
    statement = buffer.str();

    if (0 != mysql_query(this->mysql, statement.c_str()))
    {
        cout << "mysql_query error" << endl;
        return "false";
    }
    else
    {
        cout << "注册成功" << endl;
        cout << uid << endl;
        return uid;
    }
}
//  根据用户名查找数据库用户是否存在
bool ChatDatabase::my_database_user_exist(const string &user)
{

    ostringstream buffer;
    buffer << "select * from user where U_LoginID = '" << user << "';";
    string statement = buffer.str();

    MYSQL_RES *res = get_MYSQL_RES(this->mysql, statement.c_str());
    if (NULL == res)
    {
        return -1;
    }

    MYSQL_ROW row = mysql_fetch_row(res);
    if (NULL == row)
        return false;
    else
    {
        return true;
    }
}
// 用户登录业务
int ChatDatabase::my_database_user_confirm(const string &loginid, const string &password)
{

    ostringstream buffer;
    buffer << "select U_PassWord from user where U_LoginID = '" << loginid << "';";
    string statement = buffer.str();

    MYSQL_RES *res = get_MYSQL_RES(this->mysql, statement.c_str());

    if (NULL == res)
    {
        // return string("");
        cout << "sql语句执行错误" << endl;
        return -1;
    }

    MYSQL_ROW row = mysql_fetch_row(res);
    if (row == nullptr)
    {
        // return string("none");
        cout << "没有该用户" << endl;
        return 2;
    }
    // string mpassword = strEncrypt(password);
    if (password == row[0])
    {
        cout << "登录成功" << endl;
        return 0;
    }
    else
    {
        return 1;
    }
}
// 根据账号名获取用户信息
User *ChatDatabase::my_database_user_getmessage(const string &loginid)
{
    ostringstream buffer;
    buffer << "select * from user where U_LoginID = '" << loginid << "';";
    string statement = buffer.str();
    MYSQL_RES *res = get_MYSQL_RES(this->mysql, statement.c_str());

    if (NULL == res)
    {
        // return string("");
        cout << "sql语句执行错误" << endl;
        return nullptr;
    }
    MYSQL_ROW row = mysql_fetch_row(res);
    if (row == nullptr)
    {
        // return string("none");
        cout << "没有该用户" << endl;
        return nullptr;
    }

    userinfo->loginid = row[1] ? row[1] : "";
    userinfo->nickname = row[2] ? row[2] : "";
    userinfo->signature = row[4] ? row[4] : "";
    userinfo->sex = row[5] ? row[5] : "";
    userinfo->birthday = row[6] ? row[6] : "";
    userinfo->pthone = row[7] ? row[7] : "";
    userinfo->email = row[8] ? row[8] : "";
    userinfo->headport = row[9] ? row[9] : "";

    if (row[10])
    {
        userinfo->age = atoi(row[10]);
    }

    userinfo->city = row[11] ? row[11] : "";
    return userinfo;
}
// 插入用户信息
int ChatDatabase::my_database_user_setmessage(const User &user)
{
    ostringstream buffer;
    buffer << "update user set U_NickName=" << "'" << user.nickname << "',"
           << "U_SignaTure=" << "'" << user.signature << "',"
           << "U_Sex=" << user.sex << ","
           << "U_Birthday=" << "'" << user.birthday << "',"
           << "U_Telepthone=" << "'" << user.pthone << "',"
           << "U_Email=" << "'" << user.email << "',"
           << "U_HeadPortrait=" << "'" << user.headport << "',"
           << "U_Age=" << to_string(user.age) << ","
           << "U_City=" << "'" << user.city << "' "
           << "where U_LoginID =" << "'" << user.loginid << "';";
    string statement = buffer.str();
    MYSQL_RES *res = get_MYSQL_RES(this->mysql, statement.c_str());

    return 0;
}
//  获取用户状态
int ChatDatabase::my_database_user_setstate(const string &loginid)
{
    ostringstream buffer;
    buffer << "select U_UserStateID from user where U_LoginID='" << loginid << "';";
    string statement = buffer.str();
    MYSQL_RES *res = get_MYSQL_RES(this->mysql, statement.c_str());
    if (res == nullptr)
    {
        cout << "sql语句执行错误" << endl;
        return -1;
    }
    MYSQL_ROW row = mysql_fetch_row(res);
    //cout << row[0] << endl;
    if (row == nullptr)
    {
        // return string("none");
        cout << "没有该用户" << endl;
        return -1;
    }
    //
    if (atoi(row[0]) == 1)
    {
        return 1;
    }
    else
    {
        return 2;
    }
}
// 设置用户状态
int ChatDatabase::my_database_user_getstate(const string &loginid, int flag)
{
    if (flag != 1 && flag != 2)
    {
        return 1;
    }
    ostringstream buffer;
    buffer << "update user set U_UserStateID=" << flag << " where U_LoginID='" << loginid << "';";
    string statement = buffer.str();
    MYSQL_RES *res = get_MYSQL_RES(this->mysql, statement.c_str());
    return 0;
}
// 将消息写入数据库
void ChatDatabase::my_database_write_offlineMsg(const Json::Value &val)
{

    const char *sender = val["sender"].asCString();
    const char *receiver = val["receiver"].asCString();
    int senderid = getid(sender);
    int receiverid = getid(receiver);
    const char *msg = val["message"].asCString();

    ostringstream buf;
    buf << "insert into messages(M_FromUserID,M_ToUserID,M_PostMessages,M_Time) "
        << "value ('" << senderid << "','" << receiverid << "','" << msg << "',now());";
    string statement = buf.str();

    if (0 != mysql_query(this->mysql, statement.c_str()))
    {
        cout << "mysql_query error" << endl;
        return;
    }
}
// 根据接收者的账户名读数据库消息
int ChatDatabase::my_database_read_offlineMsg(vector<string> &vec, string receiver)
{
    int receiverid = getid(receiver.c_str());
    ostringstream buf;
    buf << "select M_PostMessages,M_Time from messages where M_ToUserID = '" << receiverid << "';";
    string stmt = buf.str();

    int ret = my_database_get_data(vec, stmt.c_str());

    // if (ret > 0)
    // {
    //     buf.str("");
    //     buf << "delete from offline_msg where receiver = '" << receiver << "';";
    //     stmt.clear();
    //     stmt = buf.str();
    //     if (0 != mysql_query(this->mysql, stmt.c_str()))
    //     {
    //         cout << "mysql_query error" << endl;
    //         return -1;
    //     }
    // }

    return ret;
}
// 模糊查找用户
vector<User> ChatDatabase::my_database_user_find(const string &nickname)
{
    vector<User> vecUser;
    User userinfo;
    ostringstream buf;
    buf << "select * from user where U_NickName like '%" << nickname << "%';";
    string statement = buf.str();
    cout<<statement<<endl;
    MYSQL_RES *res = get_MYSQL_RES(this->mysql, statement.c_str());
    if (NULL == res)
    {
        cout << "sql语句执行错误" << endl;
        exit(-1);
    }
    MYSQL_ROW row;
    while ((row = mysql_fetch_row(res)))
    {
        userinfo.loginid = row[1] ? row[1] : "";
        userinfo.nickname = row[2] ? row[2] : "";
        // userinfo.signature = row[4] ? row[4] : "";
        // userinfo.sex = row[5] ? row[5] : "";
        // userinfo.birthday = row[6] ? row[6] : "";
        // userinfo.pthone = row[7] ? row[7] : "";
        // userinfo.email = row[8] ? row[8] : "";
        // userinfo.headport = row[9] ? row[9] : "";
        // if (row[10])
        // {
        //     userinfo.age = atoi(row[10]);
        // }
        // userinfo.city = row[11] ? row[11] : "";
        vecUser.push_back(userinfo);
    }
    return vecUser;
}
// 返回好友map
map<const string, Friends> ChatDatabase::my_database_getfriends(const string &loginid)
{
    map<const string, Friends> friendsmap;
    Friends friendinfo;
    // 获取用户id
    int userid = getid(loginid.c_str());
    ostringstream buf;
    buf << "select * from friends where F_UserID = '" << userid << "';";
    string statement = buf.str();

    MYSQL_RES *res = get_MYSQL_RES(this->mysql, statement.c_str());
    if (NULL == res)
    {
        cout << "sql语句执行错误" << endl;
        exit(-1);
    }

    MYSQL_ROW row;
    while ((row = mysql_fetch_row(res)))
    {
        // 得到好友账户
        const string friendid = getlogin(atoi(row[1]));

        // 包装好友结构体
        friendinfo.firendid = atoi(row[1]);
        friendinfo.name = row[3];
        friendinfo.FriendGroups = atoi(row[4]);

        // 放入map
        friendsmap[friendid] = friendinfo;
    }

    return friendsmap;
}
//
int ChatDatabase::my_newfriend(const newFriends &newfrinfo)
{
    int ownid = getid(newfrinfo.loginid.c_str());
    int friendid = getid(newfrinfo.newfriendid.c_str());
    ostringstream buf;
    buf << "insert into newfriends(NF_UserID,NF_NewFriend,NF_Datatime,NF_Proof) value(" << ownid << "," << friendid << ",now(),'" << newfrinfo.proof << "');";
    string statement = buf.str();
    if (0 != mysql_query(this->mysql, statement.c_str()))
    {
        cout << "mysql_query error" << endl;
        return 0;
    }
    return 1;
}

//
vector<newFriends> ChatDatabase::my_getnewfriends(const string &loginid)
{
    int logid = getid(loginid.c_str());
    ostringstream buf;
    buf << "select * from newfriends where NF_NewFriend = '" << logid << "';";
    string statement = buf.str();
    MYSQL_RES *res = get_MYSQL_RES(this->mysql, statement.c_str());
    if (NULL == res)
    {
        cout << "sql语句执行错误" << endl;
        exit(-1);
    }
    MYSQL_ROW row;
    vector<newFriends> vecnewfri;
    newFriends nfrd;
    while ((row = mysql_fetch_row(res)))
    {
        nfrd.loginid = getlogin(atoi(row[1])) ? getlogin(atoi(row[1])) : "";
        nfrd.newfriendid = getlogin(atoi(row[2])) ? getlogin(atoi(row[2])) : "";
        nfrd.time = row[3] ? row[3] : "";
        nfrd.proof = row[4] ? row[4] : "";
        vecnewfri.push_back(nfrd);
    }
    return vecnewfri;
}
//
int ChatDatabase::add_friend(const string &loginid, const string &fried, const string &ownname, const string &friname)
{
    int logid = getid(loginid.c_str());
    int frid = getid(fried.c_str());
    ostringstream buf;
    buf << "insert into friends(F_FirendID,F_UserID,F_Name) values(" << frid << "," << logid << ",'" << friname << "'),"
        << "(" << logid << "," << frid << ",'" << ownname << "');";
    string statement = buf.str();
    cout<<statement<<endl;
    if (0 != mysql_query(this->mysql, statement.c_str()))
    {
        cout << "mysql_query error" << endl;
        return 0;
    }
    return 1;
}